

package com.example.config;
import cn.hutool.core.util.StrUtil;
import com.event.cache.iface.INamespaceCacheManager;
import com.example.constant.CacheNameEnum;
import com.example.constant.NamespaceRefNameEnum;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import javax.annotation.Resource;
import java.time.Duration;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Redis Cache配置
 */
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private RedisConnectionFactory redisConnectionFactory;

    @Resource
    private INamespaceCacheManager namespaceCacheManager;

    public static final String PREFIX_TAG = ":";

    @Bean
    @Primary
    public CacheManager cacheManager() {
        CacheNameEnum[] cacheNameEnums = CacheNameEnum.values();

        Map<String, RedisCacheConfiguration> configMap = Arrays.stream(cacheNameEnums).collect(Collectors.toMap(CacheNameEnum::getName, cacheNameEnum -> {
            return getRedisCacheConfiguration(cacheNameEnum);
        }));
        // 注册过滤名称
        Arrays.stream(NamespaceRefNameEnum.RefNameEnum.values()).forEach(item ->{
            namespaceCacheManager.registerFilterName(item.getNamespace(), StrUtil.split(item.getRefName(),","));
        });
        return new CustomRedisCacheManager(redisConnectionFactory,configMap,namespaceCacheManager);
    }


    private RedisCacheConfiguration getRedisCacheConfiguration(CacheNameEnum cacheManagerTypeEnum){
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(getTtl(cacheManagerTypeEnum))
                .computePrefixWith(cacheName -> cacheManagerTypeEnum.getName() + PREFIX_TAG)
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getKeySerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
    }

    private Duration getTtl(CacheNameEnum cacheManagerTypeEnum){
        if(cacheManagerTypeEnum.getTimeUnit() == TimeUnit.MINUTES) return Duration.ofMinutes(cacheManagerTypeEnum.getEffectiveTime());
        if(cacheManagerTypeEnum.getTimeUnit() == TimeUnit.SECONDS) return Duration.ofSeconds(cacheManagerTypeEnum.getEffectiveTime());
        if(cacheManagerTypeEnum.getTimeUnit() == TimeUnit.DAYS) return Duration.ofDays(cacheManagerTypeEnum.getEffectiveTime());
        if(cacheManagerTypeEnum.getTimeUnit() == TimeUnit.HOURS) return Duration.ofHours(cacheManagerTypeEnum.getEffectiveTime());
        return Duration.ofMillis(cacheManagerTypeEnum.getEffectiveTime());
    }
}
